package br.com.winesys.geta.databinding.component.selector;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import br.com.winesys.geta.base.ExceptionMessage;
import br.com.winesys.geta.persistence.jpa.JPAEntityManagerFactoryBuilder;

public abstract class JPAObjectSelector<Entity> extends ObjectSelector<Entity> {

	private Map<String, Object> parameters = new HashMap<String, Object>();

	@Override
	public void listSelectable() {
		EntityManager manager = JPAEntityManagerFactoryBuilder.getEntityManagerFactory(this.getPersistenceUnit()).createEntityManager();
		List<Entity> result = null;
		try {
			Query query = manager.createQuery(this.getListQuery());
			for (String key : this.parameters.keySet()) {
				query.setParameter(key, this.parameters.get(key));
			}
			result = query.getResultList();
			this.itemsListed(result);
		} catch (Exception ex) {
			ExceptionMessage.showMessage(this, ex);
		} finally {
			try {
				manager.close();
			} catch (Exception ex) {
			}
		}
	}

	@Override
	public void load(Serializable key) {
		EntityManager manager = JPAEntityManagerFactoryBuilder.getEntityManagerFactory(this.getPersistenceUnit()).createEntityManager();
		Entity result = null;
		try {
			Map<String, Object> params = new HashMap<String, Object>(this.parameters);
			params.put("key", key);
			Query query = manager.createQuery(this.getLoadQuery());
			for (String str : params.keySet()) {
				query.setParameter(str, params.get(str));
			}
			List<Entity> list = query.getResultList();
			result = list.isEmpty() ? null : list.get(0);
			this.itemLoaded(result);
		} catch (Exception ex) {
			ExceptionMessage.showMessage(this, "Não foi possível carregar o item informado.", ex);
		} finally {
			manager.close();
		}
	}

	public void setParameter(String key, Object value) {
		this.parameters.put(key, value);
	}

	public Set<String> getParametersKeys() {
		return new TreeSet<String>(this.parameters.keySet());
	}

	public Object getParameter(String key) {
		return this.parameters.get(key);
	}

	protected abstract String getPersistenceUnit();

	protected abstract String getListQuery();

	protected abstract String getLoadQuery();
}